//
// Created by wujehy on 2020/5/21.
//

#include "KeyPairData.h"
#include "curve25519-donna.h"
#include "SecurityCommon.h"
#include "Common.h"
#include "ed25519/additions/curve_sigs.h"

using namespace GeeJoan::Common;
static const uint8_t basepoint[32] = {9};

int KeyPairData::generateKeyPair()
{
    int result = 0;
    uint8_t temp_pri[COMMON_KEY_PAIR_SIZE] = {0};

    uint8_t temp_pub[COMMON_KEY_PAIR_SIZE] = {0};
    result = common_random_generator( temp_pri, COMMON_KEY_PAIR_SIZE );

    if (result < 0)
    {
        // 失败
    } else
    {
        //成功  生成 公钥
        result = curve25519_donna( temp_pub, temp_pri, basepoint );
    }

    if (result < 0)
    {
        //失败 清除公私钥
        m_privateKey = "";
        m_publicKey = "";
    } else
    {
        m_privateKey = std::string((char *) temp_pri, COMMON_KEY_PAIR_SIZE );
        m_publicKey = std::string((char *) temp_pub, COMMON_KEY_PAIR_SIZE );
    }

    return result;
}

int KeyPairData::Calculation(std::string &out_shared_key, std::string &publiceKey)
{
    if (publiceKey.empty() || m_privateKey.empty())
    {
        // 空
        return COMMON_ERROR_CODE_INVAL;
    }
    uint8_t temp_share[COMMON_KEY_PAIR_SIZE] = {0};


    int result = curve25519_donna( temp_share, (uint8_t *) m_privateKey.c_str(), (uint8_t *) publiceKey.c_str());

    if (result < 0)
    {
        return COMMON_ERROR_CODE_FAIL;
    } else
    {

        out_shared_key = std::string((char *) temp_share, COMMON_KEY_PAIR_SIZE );
        return COMMON_ERROR_CODE_SUCCESS;
    }

}

int KeyPairData::Calculation(std::string &out_shared_key, Common::KeyPairData &otherKeyPair)
{
    return this->Calculation( out_shared_key, otherKeyPair.m_publicKey );

}

const std::string &KeyPairData::getMPublicKey() const
{
    return m_publicKey;
}

const std::string &KeyPairData::getMPrivateKey() const
{
    return m_privateKey;
}

int KeyPairData::Signature(std::string &signature_out, std::string &inMessage)
{

    if (m_privateKey.empty())
    {
        return COMMON_ERROR_CODE_INVAL;
    }

    uint8_t sign_temp[COMMON_SIGNATURE_SIZE] = {0};

    uint8_t random[COMMON_SIGNATURE_RAMDON_SIZE];


    int result = common_random_generator( random, COMMON_SIGNATURE_RAMDON_SIZE );

    if (result == 0)
    {
        result = curve25519_sign( sign_temp, (uint8_t *) m_privateKey.c_str(), (uint8_t *) inMessage.c_str(),
                                  inMessage.size(), random );
    }

    if (result < 0)
    {
        // 失败
        return COMMON_ERROR_CODE_FAIL;
    } else
    {
        // 成
        signature_out = std::string((char *) sign_temp, COMMON_SIGNATURE_SIZE );
        return COMMON_ERROR_CODE_SUCCESS;
    }

}

int KeyPairData::Verify(std::string &signature, std::string &public_key, std::string &inMessage)
{
    if (public_key.empty() || public_key.size() != 32)
    {
        return COMMON_ERROR_CODE_UNKNOW;
    }

    if (signature.size() != COMMON_SIGNATURE_SIZE)
    {
        return COMMON_ERROR_CODE_INVAL;
    }


    int ret = curve25519_verify((uint8_t *) signature.c_str(), (uint8_t *) public_key.c_str(),
                                (uint8_t *) inMessage.c_str(), inMessage.size());

    return ret == 0 ? COMMON_ERROR_CODE_SUCCESS : COMMON_ERROR_CODE_FAIL;
}

//
KeyPairData::KeyPairData(std::string serialize)
{
    if(serialize.empty()||serialize.length() != 129)
    {
        // 空密钥 或者错误密钥
    } else
    {
        // 密钥进行保存
        // 反向操作
        printf("test 1 ,%s \n" ,serialize.substr(0,64).c_str() );
        printf("test 2 ,%s \n" ,serialize.substr(65,129).c_str() );
        m_publicKey = HexToString(serialize.substr(0,64));
        m_privateKey = HexToString(serialize.substr(65,129));

    }
}

std::string KeyPairData::getSerializeKeyPair()
{
//    printf("test 1 ,%s \n" ,StringToHex(m_publicKey).c_str() );
//    printf("test 2 ,%s \n" ,StringToHex(m_privateKey).c_str() );

    return StringToHex(m_publicKey)+"."+StringToHex(m_privateKey);
}
